package com.amway.qy.core.service.impl;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.amway.qy.core.constants.QyWechatUrls;
import com.amway.qy.core.service.QyAccessTokenService;
import com.amway.qy.core.service.QyTagService;
import com.amway.qy.resource.result.tag.QyEnrichTagResult;
import com.amway.qy.resource.result.tag.QyListUserByTagResult;
import com.amway.qy.resource.result.tag.QyListTagResult;
import com.amway.qy.resource.result.tag.QyTagResult;
import com.amway.qy.resource.tag.QyEnrichByTag;
import com.amway.qy.resource.tag.QyTag;
import com.amway.qy.util.common.QyHttpClientUtils;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;

public class QyTagServiceImpl implements QyTagService {
	private static final Logger logger = LoggerFactory.getLogger(QyTagServiceImpl.class);
	private QyAccessTokenService accessTokenManager;

	public QyTagServiceImpl(QyAccessTokenService accessTokenManager) {
		this.accessTokenManager = accessTokenManager;
	}

	@Override
	public QyAccessTokenService getQyAccessTokenService() {
		return accessTokenManager;
	}

	@Override
	public void setQyAccessTokenService(QyAccessTokenService tokenService) {
		this.accessTokenManager = tokenService;
	}

	@Override
	public QyTagResult createTag(QyTag tag) {
		
		logger.debug("createTag -->"+tag);
		
		List<NameValuePair> paramsMap = new ArrayList<NameValuePair>();
		paramsMap.add(new BasicNameValuePair("access_token", accessTokenManager.getAccessToken()));
		String ret = QyHttpClientUtils.httpsPostJson(QyWechatUrls.CREATE_TAG,paramsMap, new Gson().toJson(tag));
		return new Gson().fromJson(ret, QyTagResult.class);
	}

	@Override
	public QyTagResult updateTag(QyTag tag) {
		
		logger.debug("updateTag -->"+tag);
		
		List<NameValuePair> paramsMap = new ArrayList<NameValuePair>();
		paramsMap.add(new BasicNameValuePair("access_token", accessTokenManager.getAccessToken()));
		String ret = QyHttpClientUtils.httpsPostJson(QyWechatUrls.UPDATE_TAG,paramsMap, new Gson().toJson(tag));
		return new Gson().fromJson(ret, QyTagResult.class);
	}

	@Override
	public QyTagResult deleteTag(int tagId) {
		
		logger.debug("deleteTag -->"+tagId);
		
		List<NameValuePair> paramsMap = new ArrayList<NameValuePair>();
		paramsMap.add(new BasicNameValuePair("access_token", accessTokenManager.getAccessToken()));
		paramsMap.add(new BasicNameValuePair("tagid", String.valueOf(tagId)));
		String ret = QyHttpClientUtils.httpsGet(QyWechatUrls.DELETE_TAG,paramsMap);
		return new Gson().fromJson(ret, QyTagResult.class);
	}

	@Override
	public QyListUserByTagResult listUserByTag(int tagId) {
		
		logger.debug("listMemeberInfoByTag -->"+tagId);
		
		List<NameValuePair> paramsMap = new ArrayList<NameValuePair>();
		paramsMap.add(new BasicNameValuePair("access_token", accessTokenManager.getAccessToken()));
		paramsMap.add(new BasicNameValuePair("tagid", String.valueOf(tagId)));
		String ret = QyHttpClientUtils.httpsGet(QyWechatUrls.LIST_USER_BY_TAG,paramsMap);
		
		return new Gson().fromJson(ret, QyListUserByTagResult.class);
	}

	@Override
	public QyListTagResult listTags() {
		
		List<NameValuePair> paramsMap = new ArrayList<NameValuePair>();
		paramsMap.add(new BasicNameValuePair("access_token", accessTokenManager.getAccessToken()));
		String ret = QyHttpClientUtils.httpsGet(QyWechatUrls.LIST_TAGS,paramsMap);
		
		return new Gson().fromJson(ret, QyListTagResult.class);
	}

	@Override
	public QyEnrichTagResult addUserToTag(QyEnrichByTag enrichInfo) {
		logger.debug("addUserToTag -->"+enrichInfo);
		List<NameValuePair> paramsMap = new ArrayList<NameValuePair>();
		paramsMap.add(new BasicNameValuePair("access_token", accessTokenManager.getAccessToken()));
		String ret = QyHttpClientUtils.httpsPostJson(QyWechatUrls.ADD_TAG_USER,paramsMap,new Gson().toJson(enrichInfo));
		return new GsonBuilder().registerTypeAdapter(QyEnrichTagResult.class, new EnrichTagDeserializer()).create().fromJson(ret, QyEnrichTagResult.class);
	}

	@Override
	public QyEnrichTagResult deleteUserFromTag(QyEnrichByTag enrichInfo) {
		logger.debug("deleteUserFromTag -->"+enrichInfo);
		List<NameValuePair> paramsMap = new ArrayList<NameValuePair>();
		paramsMap.add(new BasicNameValuePair("access_token", accessTokenManager.getAccessToken()));
		String ret = QyHttpClientUtils.httpsPostJson(QyWechatUrls.REMOVE_TAG_USER,paramsMap,new Gson().toJson(enrichInfo));
		return new GsonBuilder().registerTypeAdapter(QyEnrichTagResult.class, new EnrichTagDeserializer()).create().fromJson(ret, QyEnrichTagResult.class);
	}


	/*
	 * 自定义反序列化器，用于解决微信官方返回的字符器包括多个值 ，却以特殊符号连接的方式提供。
	 * e.g 
	 * 	invaliduser: A|B|C
	 *  如上内容，无法于应用层方便操作，需要提供List的操作方式。即invaliduser:[A,B,C].
	 * 
	 */
	private static class EnrichTagDeserializer implements JsonDeserializer<QyEnrichTagResult> {

		@Override
		public QyEnrichTagResult deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
			final JsonObject jsonObject = json.getAsJsonObject();
			
			final QyEnrichTagResult result = new QyEnrichTagResult();
			result.setErrcode(jsonObject.get("errcode").getAsLong());
			result.setErrmsg(jsonObject.get("errmsg").getAsString());
			if(!result.isSuccess()){				
				result.setInvalidlist(Arrays.asList(jsonObject.get("invalidlist").getAsString().split("\\|")));
				final JsonArray invalidParty = jsonObject.get("invalidparty").getAsJsonArray();		
				final Integer[] parties = new Integer[invalidParty.size()];
				for(int i=0;i<parties.length;i++){
					parties[i]=invalidParty.get(i).getAsInt();
				}
				
				result.setInvalidparty(Arrays.asList(parties));
			}
			return result;
		}
		
	}
}
